From 8fda9727bb023e28ef4e27a88b1bd1dfb20f27e3 Mon Sep 17 00:00:00 2001 From: robertl Date: Tue, 11 Feb 2003 19:47:45 +0000 Subject: [PATCH] Multitude of memory "leaks" fixed. From Ron Parker. --- gpsbabel/Makefile | 1 + gpsbabel/cetus.c | 3 +- gpsbabel/csv.c | 5 ++- gpsbabel/csv_util.c | 43 ++++++++++++++------- gpsbabel/csv_util.h | 10 +++++ gpsbabel/defs.h | 57 +++++++++++++++++++++++++++- gpsbabel/dna.c | 2 +- gpsbabel/duplicate.c | 43 +++++++++++---------- gpsbabel/filter_vecs.c | 14 +++++-- gpsbabel/garmin.c | 4 +- gpsbabel/gcdb.c | 19 ++++++---- gpsbabel/geo.c | 3 ++ gpsbabel/gpsdrive.c | 11 ++++-- gpsbabel/gpspilot.c | 1 + gpsbabel/gpx.c | 39 +++++++++++++++---- gpsbabel/holux.c | 9 ++++- gpsbabel/magnav.c | 1 + gpsbabel/magproto.c | 13 ++++--- gpsbabel/main.c | 18 ++++++++- gpsbabel/mkshort.c | 44 ++++++++++++--------- gpsbabel/mxf.c | 5 ++- gpsbabel/ozi.c | 9 +++-- gpsbabel/pcx.c | 2 - gpsbabel/position.c | 12 ++++-- gpsbabel/psp.c | 4 +- gpsbabel/route.c | 36 ++++++++++++++++++ gpsbabel/tmpro.c | 6 +-- gpsbabel/tpg.c | 5 ++- gpsbabel/util.c | 86 +++++++++++++++++++++++++++++++++++++++++- gpsbabel/vecs.c | 12 +++++- gpsbabel/waypt.c | 55 +++++++++++++++++++++++++++ gpsbabel/xcsv.c | 67 +++++++++++++++++++------------- gpsbabel/xmapwpt.c | 7 +++- 33 files changed, 510 insertions(+), 136 deletions(-) diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index 3999d6357..c1eb0c6fe 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -1,3 +1,4 @@ +# add -DDEBUG_MEM to turn on memory allocation logging CFLAGS=-g -Icoldsync INSTALL_TARGETDIR=/usr/local/ diff --git a/gpsbabel/cetus.c b/gpsbabel/cetus.c index 6cf2ca227..e5ddd603f 100644 --- a/gpsbabel/cetus.c +++ b/gpsbabel/cetus.c @@ -266,6 +266,7 @@ cetus_writewpt(waypoint *wpt) if (pdb_AppendRecord(opdb, opdb_rec)) { fatal(MYNAME ": libpdb couldn't append record\n"); } + xfree(rec); } struct hdr{ @@ -325,7 +326,7 @@ data_write(void) } pdb_Write(opdb, fileno(file_out)); - free(htable); + xfree(htable); } diff --git a/gpsbabel/csv.c b/gpsbabel/csv.c index e6c04b2ae..8faaf766a 100644 --- a/gpsbabel/csv.c +++ b/gpsbabel/csv.c @@ -138,6 +138,9 @@ data_read(void) wpt_tmp->shortname = mkshort(mkshort_handle, wpt_tmp->description); waypt_add(wpt_tmp); } + else { + waypt_free(wpt_tmp); + } } else { /* empty line */ @@ -172,7 +175,7 @@ csv_waypt_pr(const waypoint *wpt) description); if (description) - free (description); + xfree(description); } diff --git a/gpsbabel/csv_util.c b/gpsbabel/csv_util.c index 3b5f2cecf..d270c897b 100644 --- a/gpsbabel/csv_util.c +++ b/gpsbabel/csv_util.c @@ -43,11 +43,16 @@ static void *mkshort_handle; /* (strip out ampersands, commas, and quotes. */ /*********************************************************************/ char * -csv_stringclean(const char *string, const char *chararray) { +#ifdef DEBUG_MEM +CSV_STRINGCLEAN(const char *string, const char *chararray, DEBUG_PARAMS) +#else +csv_stringclean(const char *string, const char *chararray) +#endif +{ char * p1; char * p2; const char * cp; - char * tmp = xstrdup(string); + char * tmp = xxstrdup(string,file,line); if ((! string) || (! chararray)) { return (tmp); @@ -80,11 +85,15 @@ csv_stringclean(const char *string, const char *chararray) { /* usage: p = csv_stringtrim(string, "\"") */ /***********************************************************************************/ char * +#ifdef DEBUG_MEM +CSV_STRINGTRIM(const char *string, const char *enclosure,DEBUG_PARAMS) +#else csv_stringtrim(const char *string, const char *enclosure) +#endif { static const char *p1 = NULL; char *p2 = NULL; - char * tmp = xstrdup(string); + char * tmp = xxstrdup(string,file,line); size_t elen; if (!strlen(string)) { @@ -146,6 +155,11 @@ csv_lineparse(const char *stringstart, const char *delimited_by, int enclosedepth = 0; short int dfound; + if (tmp) { + xfree(tmp); + tmp = NULL; + } + if (!p) { /* first pass thru */ p = stringstart; @@ -156,11 +170,6 @@ csv_lineparse(const char *stringstart, const char *delimited_by, } } - if (tmp) { - free(tmp); - tmp = NULL; - } - /* the beginning of the string we start with (this pass) */ sp = p; @@ -398,6 +407,7 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) } else if (strcmp(fmp->key, "ICON_DESCR") == 0) { wpt->icon_descr = csv_stringtrim(s, ""); + wpt->icon_descr_is_dynamic = 1; } else /* LATITUDE CONVERSIONS**************************************************/ @@ -536,6 +546,9 @@ xcsv_data_read(void) if (elem == &xcsv_file.ifield) { /* we've wrapped the queue. so stop parsing! */ + while (s) { + s=csv_lineparse(NULL, "\xff","",linecount); + } break; } @@ -565,10 +578,10 @@ xcsv_waypt_pr(const waypoint *wpt) queue *elem, *tmp; if (wpt->shortname) { - anyname = xstrdup(mkshort(mkshort_handle, wpt->shortname)); + anyname = mkshort(mkshort_handle, wpt->shortname); } else if (wpt->description) { - anyname = xstrdup(mkshort(mkshort_handle, wpt->description)); + anyname = mkshort(mkshort_handle, wpt->description); } else if (wpt->notes) { anyname = xstrdup(wpt->notes); @@ -576,7 +589,9 @@ xcsv_waypt_pr(const waypoint *wpt) anyname = xstrdup(""); if ((anyname) && (global_opts.synthesize_shortnames)) { - anyname = mkshort(mkshort_handle, anyname); + char *oldname = anyname; + anyname = mkshort(mkshort_handle, oldname); + xfree(oldname); } if ((! wpt->shortname) || (global_opts.synthesize_shortnames)) { @@ -746,13 +761,13 @@ xcsv_waypt_pr(const waypoint *wpt) fprintf (xcsv_file.xcsvfp, "%s", xcsv_file.record_delimiter); if (shortname) - free(shortname); + xfree(shortname); if (description) - free(description); + xfree(description); if (anyname) - free(anyname); + xfree(anyname); index++; } diff --git a/gpsbabel/csv_util.h b/gpsbabel/csv_util.h index 2fdffed32..122b27417 100644 --- a/gpsbabel/csv_util.h +++ b/gpsbabel/csv_util.h @@ -20,13 +20,23 @@ /* function prototypes */ char * +#ifndef DEBUG_MEM csv_stringtrim(const char *string, const char *enclosure); +#else +CSV_STRINGTRIM(const char *string, const char *enclosure, DEBUG_PARAMS); +#define csv_stringtrim( s, e ) CSV_STRINGTRIM( s, e, __FILE__, __LINE__); +#endif char * csv_lineparse(const char *stringstart, const char *delimited_by, const char *enclosed_in, const int line_no); char * +#ifndef DEBUG_MEM csv_stringclean(const char *string, const char *chararray); +#else +CSV_STRINGCLEAN(const char *string, const char *chararray,DEBUG_PARAMS); +#define csv_stringclean(s,c) CSV_STRINGCLEAN(s,c,__FILE__,__LINE__); +#endif void xcsv_data_read(void); diff --git a/gpsbabel/defs.h b/gpsbabel/defs.h index 34de88024..d97f797de 100644 --- a/gpsbabel/defs.h +++ b/gpsbabel/defs.h @@ -154,6 +154,7 @@ typedef struct { char *notes; char *url; char *url_link_text; + int icon_descr_is_dynamic; const char *icon_descr; time_t creation_time; geocache_data gc_data; @@ -172,7 +173,14 @@ typedef void (*ff_init) (char const *, char const *); typedef void (*ff_deinit) (void); typedef void (*ff_read) (void); typedef void (*ff_write) (void); + +#ifndef DEBUG_MEM char * get_option(const char *iarglist, const char *argname); +#else +#define DEBUG_PARAMS const char *file, const int line +char *GET_OPTION(const char *iarglist, const char *argname, DEBUG_PARAMS); +#define get_option(iarglist, argname) GET_OPTION(iarglist, argname, __FILE__, __LINE__) +#endif typedef void (*filter_init) (char const *); typedef void (*filter_process) (void); @@ -185,21 +193,34 @@ typedef void (*route_hdr)(const route_head *); typedef void (*route_trl)(const route_head *); void waypt_add (waypoint *); void waypt_del (waypoint *); +void waypt_free (waypoint *); void waypt_disp_all(waypt_cb); -void route_disp_all(route_hdr, route_trl, waypt_cb); +void waypt_flush(queue *); +void waypt_flush_all(); unsigned int waypt_count(void); route_head *route_head_alloc(void); void route_add (waypoint *); void route_add_wpt(route_head *rte, waypoint *wpt); void route_add_head(route_head *rte); +void route_disp_all(route_hdr, route_trl, waypt_cb); +void route_free (route_head *); +void route_flush( queue *); +void route_flush_all(); /* * All shortname functions take a shortname handle as the first arg. * This is an opaque pointer. Callers must not fondle the contents of it. */ +#ifndef DEBUG_MEM char *mkshort (void *, const char *); void *mkshort_new_handle(void); +#else +char *MKSHORT(void *, const char *, DEBUG_PARAMS); +void *MKSHORT_NEW_HANDLE(DEBUG_PARAMS); +#define mkshort( a, b) MKSHORT(a,b,__FILE__, __LINE__) +#define mkshort_new_handle() MKSHORT_NEW_HANDLE(__FILE__,__LINE__) +#endif void *mkshort_del_handle(void *h); void setshort_length(void *, int n); void setshort_badchars(void *, const char *); @@ -245,14 +266,48 @@ void disp_formats(void); void printposn(const coord *c, int is_lat); filter_vecs_t * find_filter_vec(char *, char **); +void free_filter_vec(filter_vecs_t *); void disp_filters(void); void disp_filter_vecs(void); +#ifndef DEBUG_MEM void *xcalloc(size_t nmemb, size_t size); void *xmalloc(size_t size); void *xrealloc(void *p, size_t s); +void xfree(void *mem); char *xstrdup(const char *s); char *xstrappend(char *src, const char *new); +#define xxcalloc(nmemb, size, file, line) xcalloc(nmemb, size) +#define xxmalloc(size, file, line) xmalloc(size) +#define xxrealloc(p, s, file, line) xrealloc(p,s) +#define xxfree(mem, file, line) xfree(mem) +#define xxstrdup(s, file, line) xstrdup(s) +#define xxstrappend(src, new, file, line) xstrappend(src, new) +#else /* DEBUG_MEM */ +void *XCALLOC(size_t nmemb, size_t size, DEBUG_PARAMS ); +void *XMALLOC(size_t size, DEBUG_PARAMS ); +void *XREALLOC(void *p, size_t s, DEBUG_PARAMS ); +void XFREE(void *mem, DEBUG_PARAMS ); +char *XSTRDUP(const char *s, DEBUG_PARAMS ); +char *XSTRAPPEND(char *src, const char *new, DEBUG_PARAMS ); +void debug_mem_open(); +void debug_mem_output( char *format, ... ); +void debug_mem_close(); +#define xcalloc(nmemb, size) XCALLOC(nmemb, size, __FILE__, __LINE__) +#define xmalloc(size) XMALLOC(size, __FILE__, __LINE__) +#define xrealloc(p, s) XREALLOC(p,s,__FILE__,__LINE__) +#define xfree(mem) XFREE(mem, __FILE__, __LINE__) +#define xstrdup(s) XSTRDUP(s, __FILE__, __LINE__) +#define xstrappend(src,new) XSTRAPPEND(src, new, __FILE__, __LINE__) +#define xxcalloc XCALLOC +#define xxmalloc XMALLOC +#define xxrealloc XREALLOC +#define xxfree XFREE +#define xxstrdup XSTRDUP +#define xxstrappend XSTRAPPEND +#endif /* DEBUG_MEM */ + + int case_ignore_strcmp(const char *s1, const char *s2); diff --git a/gpsbabel/dna.c b/gpsbabel/dna.c index d10430c5e..4fbc8c30e 100644 --- a/gpsbabel/dna.c +++ b/gpsbabel/dna.c @@ -147,7 +147,7 @@ dna_waypt_pr(const waypoint *wpt) description); if (description) - free (description); + xfree(description); } diff --git a/gpsbabel/duplicate.c b/gpsbabel/duplicate.c index 6626e24d6..6dbf569fe 100644 --- a/gpsbabel/duplicate.c +++ b/gpsbabel/duplicate.c @@ -25,8 +25,8 @@ extern queue waypt_head; static int duplicate_shortname = 0; static int duplicate_location = 0; -char *snopt; -char *lcopt; +static char *snopt = NULL; +static char *lcopt = NULL; static arglist_t dup_args[] = { @@ -132,6 +132,18 @@ addnode (btree_node * tree, btree_node * newnode) return (tree); } +void +free_tree (btree_node *tree) +{ + if ( tree->left ) { + free_tree(tree->left); + } + if ( tree->right ) { + free_tree(tree->right); + } + xfree(tree); +} + void duplicate_process(void) { @@ -140,6 +152,7 @@ duplicate_process(void) btree_node * newnode, * btmp, * ftmp, * sup_tree = NULL; unsigned long crc = 0; struct { char shortname[32]; char lat[13]; char lon[13]; } dupe; + waypoint * delwpt = NULL; QUEUE_FOR_EACH(&waypt_head, elem, tmp) { waypointp = (waypoint *) elem; @@ -164,30 +177,22 @@ duplicate_process(void) btmp = addnode(sup_tree, newnode); if (btmp == NULL) { + if ( delwpt ) { + waypt_free(delwpt); + } + delwpt = waypointp; waypt_del(waypointp); /* collision */ - free(newnode); + xfree(newnode); } else { sup_tree = btmp; } } - - btmp = sup_tree->right; - - while (btmp) { - ftmp = btmp; - btmp = btmp->right; - free(ftmp); - } - - btmp = sup_tree->left; - - while (btmp) { - ftmp = btmp; - btmp = btmp->left; - free(ftmp); + + if ( delwpt ) { + waypt_free(delwpt); } - free(sup_tree); + free_tree(sup_tree); } void diff --git a/gpsbabel/filter_vecs.c b/gpsbabel/filter_vecs.c index e01ef8b07..47e22ba72 100644 --- a/gpsbabel/filter_vecs.c +++ b/gpsbabel/filter_vecs.c @@ -68,7 +68,7 @@ find_filter_vec(char *const vecname, char **opts) res = strchr(vecname, ','); if (res) { - *opts = strchr(vecname, ',')+1; + *opts = res+1; if (vec->vec->args) { for (ap = vec->vec->args; ap->argstring; ap++){ @@ -79,14 +79,22 @@ find_filter_vec(char *const vecname, char **opts) *opts = NULL; } - free(v); + xfree(v); return vec->vec; } - free(v); + xfree(v); return NULL; } +void +free_filter_vec( filter_vecs_t *fvec ) +{ + if ( fvec->args && fvec->args->argval && *(fvec->args->argval) ) { + xfree(*(fvec->args->argval)); + } +} + /* * Display the available formats in a format that's easy for humans to * parse for help on available command line options. diff --git a/gpsbabel/garmin.c b/gpsbabel/garmin.c index 5fa38cb72..1478d3ef5 100644 --- a/gpsbabel/garmin.c +++ b/gpsbabel/garmin.c @@ -132,7 +132,7 @@ track_read(void) while(--ntracks) { GPS_Track_Del(&array[ntracks]); } - free(array); + xfree(array); } static void @@ -263,7 +263,7 @@ data_write(void) for (i = 0; i < n; ++i) { GPS_Way_Del(&way[i]); } - free(way); + xfree(way); } ff_vecs_t garmin_vecs = { diff --git a/gpsbabel/gcdb.c b/gpsbabel/gcdb.c index 2021b665a..20187d186 100644 --- a/gpsbabel/gcdb.c +++ b/gpsbabel/gcdb.c @@ -53,6 +53,8 @@ static const char *out_fname; struct pdb *opdb; struct pdb_record *opdb_rec; +static char *tbuf = NULL; +static char *tbufp = NULL; static void rd_init(const char *fname, const char *args) @@ -83,6 +85,8 @@ static void wr_deinit(void) { fclose(file_out); + if ( tbuf ) + xfree(tbuf); } static void @@ -188,14 +192,18 @@ data_read(void) free_pdb(pdb); } + static int gcdb_add_to_rec(struct dbrec *rec, char *fldname, gcdb_rectype rectype, void *data) { int length; - static char *tbuf; - static char *tbufp; static int rec_cnt; + if (!tbuf) { + tbuf = xcalloc(MAXRECSZ, 1); + tbufp = tbuf; + } + if (fldname == NULL) { length = tbufp - tbuf; be_write16(&rec->nflds, rec_cnt); @@ -205,11 +213,6 @@ gcdb_add_to_rec(struct dbrec *rec, char *fldname, gcdb_rectype rectype, void *da return length; } - if (!tbuf) { - tbuf = xcalloc(MAXRECSZ, 1); - tbufp = tbuf; - } - be_write16(&rec->dbfld[rec_cnt].fldtype,rectype); strncpy(rec->dbfld[rec_cnt].fldname, fldname, 4); @@ -307,7 +310,7 @@ gcdb_write_wpt(const waypoint *wpt) fatal(MYNAME ": libpdb couldn't append record\n"); } - free(rec); + xfree(rec); } static void diff --git a/gpsbabel/geo.c b/gpsbabel/geo.c index 32c1f9b0e..86dd7850b 100644 --- a/gpsbabel/geo.c +++ b/gpsbabel/geo.c @@ -161,6 +161,9 @@ geo_rd_init(const char *fname, const char *args) void geo_rd_deinit(void) { + if ( cdatastr ) { + xfree(cdatastr); + } fclose(fd); } diff --git a/gpsbabel/gpsdrive.c b/gpsbabel/gpsdrive.c index 8fc02614e..fa18191e6 100644 --- a/gpsbabel/gpsdrive.c +++ b/gpsbabel/gpsdrive.c @@ -109,6 +109,7 @@ data_read(void) case 3: rtrim(s); wpt_tmp->icon_descr = xstrdup(s); + wpt_tmp->icon_descr_is_dynamic = 1; break; default: fprintf (stderr, "%s: Warning: unmapped data fields on line %d.\n", @@ -142,6 +143,7 @@ gpsdrive_waypt_pr(const waypoint *wpt) double lon,lat; char * shortname = NULL; char *isrc, *owpt; + char *tmpstr; lon = wpt->position.longitude.degrees; lat = wpt->position.latitude.degrees; @@ -159,8 +161,11 @@ gpsdrive_waypt_pr(const waypoint *wpt) if (( shortname == NULL ) && wpt->notes ) shortname = csv_stringclean(wpt->notes, ",\""); - if ( shortname ) + if ( shortname ) { + tmpstr = shortname; shortname = mkshort(mkshort_wr_handle, shortname); + xfree(tmpstr); + } } fprintf(file_out, "%s %08.5f %08.5f", @@ -170,12 +175,12 @@ gpsdrive_waypt_pr(const waypoint *wpt) if (wpt->icon_descr) { char *s = csv_stringclean(wpt->icon_descr, " "); fprintf(file_out, " %s", s); - free(s); + xfree(s); } fprintf(file_out, "\n"); if (shortname) - free (shortname); + xfree(shortname); } diff --git a/gpsbabel/gpspilot.c b/gpsbabel/gpspilot.c index bfa9b5728..9909ba82b 100644 --- a/gpsbabel/gpspilot.c +++ b/gpsbabel/gpspilot.c @@ -172,6 +172,7 @@ gpspilot_writewpt(const waypoint *wpt) if (pdb_AppendRecord(opdb, opdb_rec)) { fatal(MYNAME ": libpdb couldn't append record\n"); } + xfree(rec); } static void diff --git a/gpsbabel/gpx.c b/gpsbabel/gpx.c index 7e2f661f7..de04a1a10 100644 --- a/gpsbabel/gpx.c +++ b/gpsbabel/gpx.c @@ -107,7 +107,7 @@ char * gpx_entitize(const char * str) strcpy(p, *(ep + 1)); strcpy(p + elen, xstr); - free(xstr); + xfree(xstr); p += elen; } @@ -412,6 +412,7 @@ gpx_end(void *data, const char *el) } if (in_icon && in_wpt) { wpt_tmp->icon_descr = xstrdup(cdatastr); + wpt_tmp->icon_descr_is_dynamic = 1; } if (in_ele) { sscanf(cdatastr, "%lf", @@ -546,7 +547,7 @@ gpx_cdata(void *dta, const XML_Char *s, int len) *cdata = xcalloc( *cdatalen + len + 1, 1); if ( estr ) { memcpy( *cdata, estr, *cdatalen); - free( estr ); + xfree( estr ); } estr = *cdata + *cdatalen; memcpy( estr, s, len ); @@ -578,6 +579,9 @@ gpx_rd_init(const char *fname, const char *args) static void gpx_rd_deinit(void) { + if ( cdatastr ) { + xfree(cdatastr); + } fclose(fd); } @@ -668,7 +672,7 @@ fprint_xml_chain( xml_tag *tag ) if ( tag->cdata ) { tmp_ent = gpx_entitize( tag->cdata ); fprintf( ofd, "%s", tmp_ent ); - free(tmp_ent); + xfree(tmp_ent); } if ( tag->child ) { fprint_xml_chain(tag->child); @@ -677,13 +681,32 @@ fprint_xml_chain( xml_tag *tag ) if ( tag->parentcdata ) { tmp_ent = gpx_entitize(tag->parentcdata); fprintf(ofd, "%s", tmp_ent ); - free(tmp_ent); + xfree(tmp_ent); } } tag = tag->sibling; } } +void free_gpx_extras( xml_tag *tag ) +{ + xml_tag *next = NULL; + while ( tag ) { + if (tag->cdata) { + xfree(tag->cdata); + } + if (tag->child) { + free_gpx_extras(tag->child); + } + if (tag->parentcdata) { + xfree(tag->parentcdata); + } + next = tag->sibling; + xfree(tag); + tag = next; + } +} + static void gpx_waypt_pr(const waypoint *waypointp) { @@ -698,7 +721,7 @@ gpx_waypt_pr(const waypoint *waypointp) if (oname) { tmp_ent = gpx_entitize(oname); fprintf(ofd, "%s\n", tmp_ent); - free(tmp_ent); + xfree(tmp_ent); } if (waypointp->description) { fprintf(ofd, ""); @@ -726,17 +749,17 @@ gpx_waypt_pr(const waypoint *waypointp) if (waypointp->url) { tmp_ent = gpx_entitize(waypointp->url); fprintf(ofd, "%s\n", tmp_ent); - free(tmp_ent); + xfree(tmp_ent); } if (waypointp->url_link_text) { tmp_ent = gpx_entitize(waypointp->url_link_text); fprintf(ofd, "%s\n", tmp_ent ); - free(tmp_ent); + xfree(tmp_ent); } if (waypointp->icon_descr) { tmp_ent = gpx_entitize(waypointp->icon_descr); fprintf(ofd, "%s\n", tmp_ent ); - free(tmp_ent); + xfree(tmp_ent); } fprint_xml_chain( waypointp->gpx_extras); diff --git a/gpsbabel/holux.c b/gpsbabel/holux.c index 1f2bd4c7d..92cc31dc3 100644 --- a/gpsbabel/holux.c +++ b/gpsbabel/holux.c @@ -143,6 +143,7 @@ static void data_read(void) wpt_tmp->position.latitude.degrees = lat; waypt_add(wpt_tmp); } + xfree(HxWpt); } @@ -153,6 +154,7 @@ char *mknshort (char *stIn,unsigned int sLen) #define MAX_STRINGLEN 255 static char strOut[MAX_STRINGLEN]; char strTmp[MAX_STRINGLEN]; + char *shortstr = NULL; if (sLen > MAX_STRINGLEN) return (stIn); @@ -162,7 +164,10 @@ char *mknshort (char *stIn,unsigned int sLen) setshort_length(mkshort_handle, sLen); setshort_mustuniq(mkshort_handle, 0); - strcpy(strTmp,mkshort(mkshort_handle, stIn)); + + shortstr = mkshort(mkshort_handle, stIn); + strcpy(strTmp,shortstr); + xfree(shortstr); memset(strOut,' ', MAX_STRINGLEN); strncpy (strOut,strTmp,strlen(strTmp)); @@ -283,7 +288,7 @@ static void data_write(void) } fclose(file_out); - free(HxWFile); + xfree(HxWFile); } diff --git a/gpsbabel/magnav.c b/gpsbabel/magnav.c index 01395ea95..64ae31041 100644 --- a/gpsbabel/magnav.c +++ b/gpsbabel/magnav.c @@ -210,6 +210,7 @@ my_writewpt(const waypoint *wpt) if (pdb_AppendRecord(opdb, opdb_rec)) { fatal(MYNAME ": libpdb couldn't append record\n"); } + xfree(rec); } static void diff --git a/gpsbabel/magproto.c b/gpsbabel/magproto.c index 4fae3957f..8b16a7922 100644 --- a/gpsbabel/magproto.c +++ b/gpsbabel/magproto.c @@ -770,6 +770,9 @@ mag_deinit(void) if(magfile_in) fclose(magfile_in); magfile_in = NULL; + if(mkshort_handle) + mkshort_del_handle(mkshort_handle); + mkshort_handle = NULL; } @@ -858,7 +861,7 @@ mag_rteparse(char *rtemsg) * alloc and chain those as we go. */ if (frag == 1) { - mag_rte_head = xmalloc(sizeof (*mag_rte_head)); + mag_rte_head = xcalloc(sizeof (*mag_rte_head),1); QUEUE_INIT(&mag_rte_head->Q); mag_rte_head->nelems = frags; } @@ -873,7 +876,7 @@ mag_rteparse(char *rtemsg) if (next_stop[0] == 0) { break; } - rte_elem = xmalloc(sizeof (*rte_elem)); + rte_elem = xcalloc(sizeof (*rte_elem),1); QUEUE_INIT(&rte_elem->Q); rte_elem->wpt_name = xstrdup(next_stop); rte_elem->wpt_icon = xstrdup(abuf); @@ -910,7 +913,7 @@ mag_rteparse(char *rtemsg) route_add_wpt(rte_head, waypt); dequeue(&re->Q); - free(re); + xfree(re); } } return 0; @@ -1122,8 +1125,8 @@ mag_waypt_pr(const waypoint *waypointp) odesc, icon_token); mag_writemsg(obuf); - free(owpt); - free(odesc); + xfree(owpt); + xfree(odesc); if (!is_file) { if (mag_error) { diff --git a/gpsbabel/main.c b/gpsbabel/main.c index 35dd1c293..805957bad 100644 --- a/gpsbabel/main.c +++ b/gpsbabel/main.c @@ -77,6 +77,15 @@ main(int argc, char *argv[]) global_opts.objective = wptdata; +#ifdef DEBUG_MEM + debug_mem_open(); + debug_mem_output( "command line: " ); + for ( argn = 1; argn < argc; argn++ ) { + debug_mem_output( "%s ", argv[argn] ); + } + debug_mem_output( "\n" ); +#endif + waypt_init(); route_init(); @@ -147,13 +156,13 @@ main(int argc, char *argv[]) case 'x': optarg = argv[argn][2] ? argv[argn]+2 : argv[++argn]; - fvecs = find_filter_vec(optarg, &fvec_opts); if (fvecs) { fvecs->f_init(fvec_opts); fvecs->f_process(); fvecs->f_deinit(); + free_filter_vec(fvecs); } break; case 'D': @@ -197,5 +206,12 @@ main(int argc, char *argv[]) if (ovecs == NULL) waypt_disp_all(waypt_disp); + waypt_flush_all(); + route_flush_all(); + +#ifdef DEBUG_MEM + debug_mem_close(); +#endif + exit(0); } diff --git a/gpsbabel/mkshort.c b/gpsbabel/mkshort.c index 9ceaef953..462212673 100644 --- a/gpsbabel/mkshort.c +++ b/gpsbabel/mkshort.c @@ -47,10 +47,14 @@ unsigned int hash_string(const char *key) } void * +#ifdef DEBUG_MEM +MKSHORT_NEW_HANDLE(DEBUG_PARAMS) +#else mkshort_new_handle() +#endif { int i; - mkshort_handle *h = xcalloc(sizeof *h, 1); + mkshort_handle *h = xxcalloc(sizeof *h, 1, file, line); for (i = 0; i < PRIME; i++) QUEUE_INIT(&h->namelist[i]); @@ -69,7 +73,7 @@ mkshort_add_to_list(mkshort_handle *h, char *name) queue *e, *t; int hash; uniq_shortname *s = xcalloc(1, sizeof (uniq_shortname)); - s->orig_shortname = strdup(name); + s->orig_shortname = xstrdup(name); hash = hash_string(name); QUEUE_FOR_EACH(&h->namelist[hash], e, t) { @@ -110,11 +114,11 @@ mkshort_del_handle(void *h) QUEUE_FOR_EACH(&hdr->namelist[i], e, t) { uniq_shortname *s = (uniq_shortname *) e; dequeue(e); - free(s->orig_shortname); - free(s); + xfree(s->orig_shortname); + xfree(s); } } - free(hdr); + xfree(hdr); } } @@ -131,6 +135,7 @@ delete_last_vowel(int start, char *istring, int *replaced) /* * Basically impelement strrchr. */ + *replaced = 0; for (l = strlen(istring); l > start; l--) { if (strchr(vowels, istring[l-1])) { char *ostring = xstrdup(istring); @@ -138,10 +143,11 @@ delete_last_vowel(int start, char *istring, int *replaced) strncpy(&ostring[l-1], &istring[l], 1+strlen(istring)-l); ostring[strlen(istring)-1] = 0; *replaced = 1; - return ostring; + strcpy( istring, ostring ); + xfree(ostring); + break; } } - *replaced = 0; return istring; } @@ -200,9 +206,13 @@ setshort_mustuniq(void *h, int i) char * +#ifdef DEBUG_MEM +MKSHORT(void *h, const char *istring, DEBUG_PARAMS ) +#else mkshort(void *h, const char *istring) +#endif { - char *ostring = xstrdup(istring); + char *ostring = xxstrdup(istring, file, line); char *nstring; char *tstring; char *cp; @@ -216,8 +226,8 @@ mkshort(void *h, const char *istring) if (( strlen(ostring) > hdl->target_len + 4) && (strncmp(ostring, "The ", 4) == 0 || strncmp(ostring, "the ", 4) == 0)) { - nstring = xstrdup(ostring + 4); - free(ostring); + nstring = xxstrdup(ostring + 4, file, line); + xfree(ostring); ostring = nstring; } @@ -225,7 +235,7 @@ mkshort(void *h, const char *istring) * Look at the back of the string for " by BLAH" and whack * it there. */ - nstring = xstrdup(ostring); + nstring = xxstrdup(ostring, file, line); l = strlen (nstring); while (l > 0) { if (strncmp(&nstring[l], " by ",4) == 0) { @@ -234,14 +244,14 @@ mkshort(void *h, const char *istring) } l --; } - free(ostring); + xfree(ostring); ostring = nstring; if (!hdl->whitespaceok) { /* * Eliminate Whitespace */ - tstring = xstrdup(ostring); + tstring = xxstrdup(ostring, file, line); l = strlen (tstring); cp = ostring; for (i=0;iposition.longitude.degrees = lon/100.0; wpt_tmp->position.latitude.degrees = lat/100.0; - wpt_tmp->icon_descr = xstrdup(icon); waypt_add(wpt_tmp); } } diff --git a/gpsbabel/position.c b/gpsbabel/position.c index ef33137dd..3a53fe98b 100644 --- a/gpsbabel/position.c +++ b/gpsbabel/position.c @@ -104,18 +104,20 @@ position_process(void) /* convert radians to integer feet */ dist = (int)((((dist * 180.0 * 60.0) / M_PI) / 1.1516) * 5280.0); - if (dist <= pos_dist) + if (dist <= pos_dist) { waypt_del(comp[i]); + waypt_free(comp[i]); + } } if (comp) - free (comp); + xfree(comp); } void position_init(const char *args) { char *fm; - const char *p; + char *p; p = get_option(args, "distance"); @@ -126,6 +128,7 @@ position_init(const char *args) { /* distance is meters */ pos_dist *= 3.2802; } + xfree(p); } } @@ -136,5 +139,6 @@ position_deinit(void) { filter_vecs_t position_vecs = { position_init, position_process, - position_deinit + position_deinit, + NULL }; diff --git a/gpsbabel/psp.c b/gpsbabel/psp.c index e23793fb2..03884e50c 100644 --- a/gpsbabel/psp.c +++ b/gpsbabel/psp.c @@ -505,8 +505,8 @@ psp_waypt_pr(const waypoint *wpt) fwrite(&tbuf[0], 1, 1, psp_file_out); /* null */ } - free (shortname); - free (description); + xfree(shortname); + xfree(description); } static void diff --git a/gpsbabel/route.c b/gpsbabel/route.c index dac5c4909..09f332d05 100644 --- a/gpsbabel/route.c +++ b/gpsbabel/route.c @@ -52,6 +52,19 @@ route_add_wpt(route_head *rte, waypoint *wpt) ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q); } +void +route_free(route_head *rte) +{ + if ( rte->rte_name ) { + xfree(rte->rte_name); + } + if ( rte->rte_desc ) { + xfree(rte->rte_desc); + } + waypt_flush(&rte->waypoint_list); + xfree(rte); +} + void route_disp (const route_head *rh, waypt_cb cb ) { @@ -75,3 +88,26 @@ route_disp_all(route_hdr rh, route_trl rt, waypt_cb wc) (*rt)(rhp); } } +void +route_flush(queue *head) +{ + queue *elem, *tmp; + route_head *last = NULL; + + QUEUE_FOR_EACH(head, elem, tmp) { + if ( last ) { + route_free(last); + } + last = (route_head *)elem; + } + if ( last ) { + route_free(last); + } + QUEUE_INIT(head); +} +void +route_flush_all() +{ + route_flush(&my_route_head); +} + diff --git a/gpsbabel/tmpro.c b/gpsbabel/tmpro.c index 529d4f1ea..379f65ae3 100644 --- a/gpsbabel/tmpro.c +++ b/gpsbabel/tmpro.c @@ -161,7 +161,7 @@ data_read(void) } if (i != 11) { - free(wpt_tmp); + xfree(wpt_tmp); fprintf (stderr, "%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n", MYNAME, i, linecount); } else { @@ -225,9 +225,9 @@ tmpro_waypt_pr(const waypoint * wpt) if (description) - free(description); + xfree(description); if (shortname) - free(shortname); + xfree(shortname); } static void diff --git a/gpsbabel/tpg.c b/gpsbabel/tpg.c index 8ef169dda..208bf1658 100644 --- a/gpsbabel/tpg.c +++ b/gpsbabel/tpg.c @@ -157,6 +157,7 @@ tpg_wr_init(const char *fname, const char *args) static void tpg_wr_deinit(void) { + mkshort_del_handle(mkshort_handle); fclose(tpg_file_out); } @@ -337,8 +338,8 @@ tpg_waypt_pr(const waypoint *wpt) /* and finally 2 unknown bytes */ fwrite(unknown2, 1, 2, tpg_file_out); - free (shortname); - free (description); + xfree(shortname); + xfree(description); } static void diff --git a/gpsbabel/util.c b/gpsbabel/util.c index 0f8b30d05..5206a80eb 100644 --- a/gpsbabel/util.c +++ b/gpsbabel/util.c @@ -24,11 +24,51 @@ #include #include +#ifdef DEBUG_MEM +#define DEBUG_FILENAME "/tmp/gpsbabel.debug" + +static FILE *debug_mem_file = NULL; +void +debug_mem_open() +{ + debug_mem_file = fopen( DEBUG_FILENAME, "a" ); +} + +void +debug_mem_output(char *format, ...) +{ + va_list args; + va_start( args, format ); + if ( debug_mem_file ) { + vfprintf( debug_mem_file, format, args ); + fflush( debug_mem_file ); + } + va_end( format ); +} + +void +debug_mem_close() +{ + if ( debug_mem_file ) { + fclose(debug_mem_file); + } + debug_mem_file = NULL; +} +#endif + void * +#ifdef DEBUG_MEM +XMALLOC(size_t size, DEBUG_PARAMS) +#else xmalloc(size_t size) +#endif { void *obj = malloc(size); +#ifdef DEBUG_MEM + debug_mem_output( "malloc, %x, %d, %s, %d\n", + obj, size, file, line ); +#endif if (!obj) { fatal("gpsbabel: Unable to allocate %d bytes of memory.\n", size); } @@ -37,9 +77,17 @@ xmalloc(size_t size) } void * +#ifdef DEBUG_MEM +XCALLOC(size_t nmemb, size_t size, DEBUG_PARAMS) +#else xcalloc(size_t nmemb, size_t size) +#endif { void *obj = calloc(nmemb, size); +#ifdef DEBUG_MEM + debug_mem_output( "calloc, %x, %d, %d, %s, %d\n", + obj, nmemb, size, file, line ); +#endif if (!obj) { fatal("gpsbabel: Unable to allocate %d bytes of memory.\n", size); @@ -48,10 +96,32 @@ xcalloc(size_t nmemb, size_t size) return obj; } +void +#ifdef DEBUG_MEM +XFREE( void *mem, DEBUG_PARAMS ) +#else +xfree( void *mem ) +#endif +{ + free(mem); +#ifdef DEBUG_MEM + debug_mem_output( "free, %x, %s, %d\n", + mem, file, line ); +#endif +} + char * +#ifdef DEBUG_MEM +XSTRDUP(const char *s, DEBUG_PARAMS ) +#else xstrdup(const char *s) +#endif { char *o = strdup(s); +#ifdef DEBUG_MEM + debug_mem_output( "strdup, %x, %x, %s, %d\n", + o, s, file, line ); +#endif if (!o) { fatal("gpsbabel: Unable to allocate %d bytes of memory.\n", strlen(s)); @@ -61,9 +131,17 @@ xstrdup(const char *s) } void * +#ifdef DEBUG_MEM +XREALLOC(void *p, size_t s, DEBUG_PARAMS ) +#else xrealloc(void *p, size_t s) +#endif { char *o = realloc(p,s); +#ifdef DEBUG_MEM + debug_mem_output( "realloc, %x, %x, %x, %s, %d\n", + o, p, s, file, line ); +#endif if (!o) { fatal("gpsbabel: Unable to realloc %d bytes of memory.\n", s); @@ -76,16 +154,20 @@ xrealloc(void *p, size_t s) * For an allocated string, realloc it and append 's' */ char * +#ifdef DEBUG_MEM +XSTRAPPEND(char *src, const char *new, DEBUG_PARAMS) +#else xstrappend(char *src, const char *new) +#endif { size_t newsz; if (!src) { - return(xstrdup(new)); + return xxstrdup(new, file, line); } newsz = strlen(src) + strlen(new) + 1; - src = xrealloc(src, newsz); + src = xxrealloc(src, newsz, file, line); strcat(src, new); return src; diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index 48f20e9dc..182692a8b 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -251,11 +251,11 @@ find_vec(char *const vecname, char **opts) *opts = NULL; } - free(v); + xfree(v); return vec->vec; } - free(v); + xfree(v); return NULL; } @@ -264,7 +264,11 @@ find_vec(char *const vecname, char **opts) * Modelled approximately after getenv. */ char * +#ifdef DEBUG_MEM +GET_OPTION(const char *iarglist, const char *argname, DEBUG_PARAMS) +#else get_option(const char *iarglist, const char *argname) +#endif { size_t arglen = strlen(argname); char *arglist; @@ -298,6 +302,10 @@ get_option(const char *iarglist, const char *argname) * The caller mustn't free or otherwise get froggy with * this data. */ + if ( rval ) { + rval = xxstrdup(rval,file, line); + } + xfree(arglist); return rval; } diff --git a/gpsbabel/waypt.c b/gpsbabel/waypt.c index 7b916040b..2ca9c6bad 100644 --- a/gpsbabel/waypt.c +++ b/gpsbabel/waypt.c @@ -118,3 +118,58 @@ find_waypt_by_name(const char *name) return NULL; } + +void +waypt_free( waypoint *wpt ) +{ + if (wpt->shortname) { + xfree(wpt->shortname); + } + if (wpt->description) { + xfree(wpt->description); + } + if (wpt->notes) { + xfree(wpt->notes); + } + if (wpt->url) { + xfree(wpt->url); + } + if (wpt->url_link_text) { + xfree(wpt->url_link_text); + } + if (wpt->icon_descr && wpt->icon_descr_is_dynamic) { + xfree((char *)(void *)wpt->icon_descr); + } + if (wpt->gpx_extras) { + free_gpx_extras(wpt->gpx_extras); + } + xfree(wpt); +} + +void +waypt_flush( queue *head ) +{ + queue *elem, *tmp; + waypoint *last = NULL; + + QUEUE_FOR_EACH(head, elem, tmp) { + if ( last ) { + waypt_free(last); + } + last = (waypoint *)elem; + } + + if ( last ) { + waypt_free(last); + } + + QUEUE_INIT(head); +} +void +waypt_flush_all() +{ + if ( mkshort_handle ) { + mkshort_del_handle( mkshort_handle ); + } + waypt_flush(&waypt_head); +} diff --git a/gpsbabel/xcsv.c b/gpsbabel/xcsv.c index 74b08a25e..1edfcbf9d 100644 --- a/gpsbabel/xcsv.c +++ b/gpsbabel/xcsv.c @@ -67,10 +67,10 @@ xcsv_destroy_style(void) if (xcsv_file.is_internal == 0) { ogp = (ogue_t *)elem; if (ogp->val) - free(ogp->val); + xfree(ogp->val); } if (elem) - free(elem); + xfree(elem); } /* destroy the epilogue */ @@ -78,10 +78,10 @@ xcsv_destroy_style(void) if (xcsv_file.is_internal == 0) { ogp = (ogue_t *)elem; if (ogp->val) - free(ogp->val); + xfree(ogp->val); } if (elem) - free(elem); + xfree(elem); } /* destroy the ifields */ @@ -89,14 +89,14 @@ xcsv_destroy_style(void) if (xcsv_file.is_internal == 0) { fmp = (field_map_t *) elem; if (fmp->key) - free(fmp->key); + xfree(fmp->key); if (fmp->val) - free(fmp->val); + xfree(fmp->val); if (fmp->printfc) - free(fmp->printfc); + xfree(fmp->printfc); } if (elem) - free(elem); + xfree(elem); } /* destroy the ofields, if they are not re-mapped to ifields. */ @@ -105,30 +105,30 @@ xcsv_destroy_style(void) if (xcsv_file.is_internal == 0) { fmp = (field_map_t *) elem; if (fmp->key) - free(fmp->key); + xfree(fmp->key); if (fmp->val) - free(fmp->val); + xfree(fmp->val); if (fmp->printfc) - free(fmp->printfc); + xfree(fmp->printfc); } if (elem) - free(elem); + xfree(elem); } if (xcsv_file.ofield) - free(xcsv_file.ofield); + xfree(xcsv_file.ofield); } if (xcsv_file.is_internal == 0) { /* other alloc'd glory */ if (xcsv_file.field_delimiter) - free(xcsv_file.field_delimiter); + xfree(xcsv_file.field_delimiter); if (xcsv_file.record_delimiter) - free(xcsv_file.record_delimiter); + xfree(xcsv_file.record_delimiter); if (xcsv_file.badchars) - free(xcsv_file.badchars); + xfree(xcsv_file.badchars); } /* return everything to zeros */ @@ -183,8 +183,10 @@ xcsv_read_style(const char *fname) if (ISSTOKEN(sbuff, "FIELD_DELIMITER")) { sp = csv_stringtrim(&sbuff[16], "\""); cp = get_char_from_constant_table(sp); - if (cp) + if (cp) { xcsv_file.field_delimiter = xstrdup(cp); + xfree(sp); + } else xcsv_file.field_delimiter = sp; } else @@ -192,8 +194,10 @@ xcsv_read_style(const char *fname) if (ISSTOKEN(sbuff, "RECORD_DELIMITER")) { sp = csv_stringtrim(&sbuff[17], "\""); cp = get_char_from_constant_table(sp); - if (cp) + if (cp) { xcsv_file.record_delimiter = xstrdup(cp); + xfree(sp); + } else xcsv_file.field_delimiter = sp; } else @@ -201,8 +205,10 @@ xcsv_read_style(const char *fname) if (ISSTOKEN(sbuff, "BADCHARS")) { sp = csv_stringtrim(&sbuff[9], "\""); cp = get_char_from_constant_table(sp); - if (cp) + if (cp) { xcsv_file.badchars = xstrdup(cp); + xfree(sp); + } else xcsv_file.badchars = sp; } else @@ -241,7 +247,7 @@ xcsv_read_style(const char *fname) i++; s = csv_lineparse(NULL, ",", "", linecount); - } + } xcsv_ifield_add(key, val, pfc); @@ -287,7 +293,7 @@ xcsv_read_style(const char *fname) /* if we have no output fields, use input fields as output fields */ if (xcsv_file.ofield_ct == 0) { if (xcsv_file.ofield) - free(xcsv_file.ofield); + xfree(xcsv_file.ofield); xcsv_file.ofield = &xcsv_file.ifield; xcsv_file.ofield_ct = xcsv_file.ifield_ct; } @@ -298,7 +304,7 @@ xcsv_read_style(const char *fname) static void xcsv_rd_init(const char *fname, const char *args) { - const char *p; + char *p; /* * if we don't have an internal style defined, we need to @@ -311,6 +317,7 @@ xcsv_rd_init(const char *fname, const char *args) fatal(MYNAME ": XCSV input style not declared. Use ... -i xcsv,style=path/to/file.style\n"); xcsv_read_style(p); + xfree(p); } xcsv_file.xcsvfp = fopen(fname, "r"); @@ -330,7 +337,7 @@ xcsv_rd_deinit(void) static void xcsv_wr_init(const char *fname, const char *args) { - const char * p; + char * p; mkshort_handle = mkshort_new_handle(); /* if we don't have an internal style defined, we need to @@ -343,20 +350,27 @@ xcsv_wr_init(const char *fname, const char *args) fatal(MYNAME ": XCSV output style not declared. Use ... -o xcsv,style=path/to/file.style\n"); xcsv_read_style(p); + xfree(p); /* set mkshort options from the command line */ if (global_opts.synthesize_shortnames) { p = get_option(args, "snlen"); - if (p) + if (p) { setshort_length(mkshort_handle, atoi(p)); + xfree(p); + } p = get_option(args, "snwhite"); - if (p) + if (p) { setshort_whitespace_ok(mkshort_handle, atoi(p)); + xfree(p); + } p = get_option(args, "snupper"); - if (p) + if (p) { setshort_mustupper(mkshort_handle, atoi(p)); + xfree(p); + } setshort_badchars(mkshort_handle, xcsv_file.badchars); } @@ -374,6 +388,7 @@ xcsv_wr_deinit(void) fclose(xcsv_file.xcsvfp); xcsv_destroy_style(); + mkshort_del_handle(mkshort_handle); } ff_vecs_t xcsv_vecs = { diff --git a/gpsbabel/xmapwpt.c b/gpsbabel/xmapwpt.c index fa3da7873..a46526b6d 100644 --- a/gpsbabel/xmapwpt.c +++ b/gpsbabel/xmapwpt.c @@ -27,7 +27,7 @@ #include "csv_util.h" #define MYNAME "XMAPWPT" -static void *mkshort_handle; +static void *mkshort_handle= NULL; static void xmapwpt_set_style() @@ -61,7 +61,7 @@ xmapwpt_set_style() /* outfields are infields */ if (xcsv_file.ofield) - free(xcsv_file.ofield); + xfree(xcsv_file.ofield); xcsv_file.ofield = &xcsv_file.ifield; xcsv_file.ofield_ct = xcsv_file.ifield_ct; @@ -106,6 +106,9 @@ xmapwpt_deinit(void) fclose(xcsv_file.xcsvfp); xcsv_destroy_style(); + if ( mkshort_handle ) + mkshort_del_handle(mkshort_handle); + mkshort_handle = NULL; } ff_vecs_t xmapwpt_vecs = { -- 2.30.2